#!/bin/sh
# This file is part of Cockpit.
#
# Copyright (C) 2013 Red Hat, Inc.
#
# Cockpit is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
#
# Cockpit is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Cockpit; If not, see <http://www.gnu.org/licenses/>.

VIRSH=/bin/virsh
QEMU_BRIDGE_HELPER=/usr/libexec/qemu-bridge-helper

BASE=$(dirname $0)
SELF=vm-prep

set -euf

usage()
{
	echo >&2 "usage: $SELF [-u]"
}

warning()
{
	echo >&2 "$SELF: $@"
}

silent()
{
	"$@" > /dev/null 2> /dev/null
	return $?
}

prepare()
{
	systemctl start libvirtd

	if silent $VIRSH net-info $NETWORK_NAME; then
		$VIRSH net-destroy $NETWORK_NAME || true
		$VIRSH net-undefine $NETWORK_NAME
	fi

	# HACK: NetworkManager races with dnsmasq-dhcp on bridge
	# https://bugzilla.redhat.com/show_bug.cgi?id=1205081
	cat > /etc/sysconfig/network-scripts/ifcfg-$NETWORK_NAME << EOF
DEVICE=$NETWORK_NAME
NM_CONTROLLED=no
EOF

    $VIRSH net-define $BASE/common/network-cockpit.xml
	$VIRSH net-autostart $NETWORK_NAME
	$VIRSH net-start $NETWORK_NAME

	if [ ! -u $QEMU_BRIDGE_HELPER ]; then
		chmod -v u+s $QEMU_BRIDGE_HELPER
	fi

	qemu_config_dirs=()
  for d in /etc/qemu-kvm/ /etc/qemu; do
      if test -f ${d}/bridge.conf; then
          qemu_config_dirs+=(${d})
      fi
	done
  if [ ${#qemu_config_dirs[@]} -eq 0 ]; then
      warning "Could not find qemu config dir"
	    exit 1
  fi

	rule="allow $NETWORK_NAME"
  for qemu_config_dir in ${qemu_config_dirs[@]}; do
      if ! silent grep -F $NETWORK_NAME ${qemu_config_dir}/bridge.conf; then
        echo "$rule" >> ${qemu_config_dir}/bridge.conf
      fi
  done

    # We really want nested virtualization
    if [ -d /sys/module/kvm_intel -a ! -f /etc/modprobe.d/kvm-intel.conf ]; then
        echo "options kvm-intel nested=1" > /etc/modprobe.d/kvm-intel.conf
        rmmod kvm-intel && modprobe kvm-intel || true
    fi
    if [ -d /sys/module/kvm_amd -a ! -f /etc/modprobe.d/kvm-amd.conf ]; then
        echo "options kvm-amd nested=1" > /etc/modprobe.d/kvm-amd.conf
        rmmod kvm-amd && modprobe kvm-amd || true
    fi
}

unprepare()
{
	if ! silent virsh net-info $NETWORK_NAME; then
		warning "the $NETWORK_NAME network has not been configured"
		exit 1
	fi

	$VIRSH net-destroy $NETWORK_NAME
	$VIRSH net-undefine $NETWORK_NAME
}

operation=prepare
args=$(getopt -o "uh" -l "help" -- "$@")
eval set -- "$args"
while [ $# -gt 0 ]; do
	case $1 in
	-h|--help)
		usage
		exit 0
		;;
	-u)
		operation=unprepare
		;;
	--)
		shift
		break
		;;
	esac
	shift
done

if [ $# -ne 0 ]; then
	usage
	exit 2
fi

uid=$(id -u)
if [ "$uid" != "0" ]; then
	warning "this script must be run as root"
	exit 1
fi

NETWORK_NAME=cockpit1
$operation
